package com.zmn.oms.dubbo.impl.normal.order;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.zmn.base.oms.common.model.es.orderwork.EsOrderWork;
import com.zmn.base.oms.common.model.es.orderwork.EsOrderWorkContact;
import com.zmn.comment.common.dro.cmt.CommentDRO;
import com.zmn.comment.dubbo.interfaces.cmt.CmtCommentListRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.dto2.data.LayuiTableDO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.oms.business.interfaces.apply.CancelApplyBService;
import com.zmn.oms.business.interfaces.order.DuplicateOrderBService;
import com.zmn.oms.business.interfaces.work.OrderWorkListBService;
import com.zmn.oms.business.interfaces.worktrack.WorkTrackBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.constant.OrderTagConsts;
import com.zmn.oms.common.dio.normal.query.OrderRefundDetailDIO;
import com.zmn.oms.common.dio.normal.query.OrderUserWaitDIO;
import com.zmn.oms.common.dio.normal.query.OrderWorkQueryDIO;
import com.zmn.oms.common.dro.normal.order.*;
import com.zmn.oms.common.enums.RefundTypeEnum;
import com.zmn.oms.dubbo.dto.zmn.order.OrderRefundDetailDRO;
import com.zmn.oms.dubbo.interfaces.normal.order.NormalOrderWorkListRemoteService;
import com.zmn.oms.dubbo.utils.DubboConsts;
import com.zmn.oms.model.bo.work.apply.cancel.CancelApplyResultBO;
import com.zmn.oms.model.entity.pay.OrderPay;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.work.OrderWorkQuery;
import com.zmn.oms.services.interfaces.pay.OrderPayService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.pay.common.constant.PayConsts;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;

import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 类描述：普通订单
 *
 * @author wangxiaokun
 * @since 2021/04/06 10:20
 */
@Slf4j
@Service(loadbalance = "roundrobin", timeout = 10000, retries = 0, version = DubboConsts.INTERFACE_VERSION, validation = "true")
public class NormalOrderWorkListRemoteServiceImpl implements NormalOrderWorkListRemoteService {

    @Autowired
    private OrderWorkListBService orderWorkListBService;
    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private WorkTrackBService workTrackBService;
    @Autowired
    OrderPayService orderPayService;
    @Autowired
    CancelApplyBService cancelApplyBService;
    @Autowired
    private DuplicateOrderBService duplicateOrderBService;
    @Reference(version = com.zmn.comment.dubbo.interfaces.utils.DubboConsts.INTERFACE_VERSION, check = false)
    private CmtCommentListRemoteService cmtCommentListRemoteService;

    @Override
    public ResponseDTO<OrderRelationDRO> getOrderRelationByOrderIdAndWorkId(Long orderId, Long workId) {
        OrderRelationDRO orderRelationDRO = orderWorkListBService.getOrderRelationByOrderIdAndWorkId(orderId, workId);
        return ResponseDTO.success(orderRelationDRO);
    }

    @Override
    @Deprecated
    public ResponseDTO<Integer> countOrderWorkByUserId(@NotNull(message = "入参不能为空") Long userId) {
        OrderWorkQuery query = new OrderWorkQuery();
        query.setUserId(userId);
        query.setWorkType(Arrays.asList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK));
        Integer count = orderWorkListBService.countOrderWorkByQuery(query);
        return ResponseDTO.success(count);
    }

    @Override
    public ResponseDTO<Integer> countOrderWorkByQuery(@NotNull(message = "入参不能为空") OrderWorkQueryDIO orderWorkQueryDIO) {
        OrderWorkQuery query = BeanMapper.map(orderWorkQueryDIO, OrderWorkQuery.class);
        query.setConcatPhone(orderWorkQueryDIO.getPhone());
        if (CollectionUtil.isNullOrEmpty(orderWorkQueryDIO.getWorkTypeList())) {
            query.setWorkType(Arrays.asList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK));
        } else {
            query.setWorkType(orderWorkQueryDIO.getWorkTypeList());
        }
        if (Objects.nonNull(orderWorkQueryDIO.getChannelId())) {
            query.setChannelIdList(Lists.newArrayList(orderWorkQueryDIO.getChannelId()));
        }
        if (Objects.nonNull(orderWorkQueryDIO.getResultStatus())) {
            query.setWorkResultStatus(orderWorkQueryDIO.getResultStatus());
        }
        query.setServCategId(orderWorkQueryDIO.getServCategIdList());
        Integer count = orderWorkListBService.countOrderWorkByQuery(query);
        return ResponseDTO.success(count);
    }

    @Override
    public ResponseDTO<Integer> countUserWaitOrderWorkByQuery(OrderUserWaitDIO orderUserWaitDIO) {
        log.info("#NormalOrderWorkListRemoteServiceImpl#countUserWaitOrderWorkByQuery orderUserWaitDIO={}", orderUserWaitDIO);
        OrderWorkQuery query = new OrderWorkQuery();
        query.setMasterId(orderUserWaitDIO.getEngineerId());
        query.setWorkResultStatus(OrderStatusConsts.WORK_RESULT_DOING);
        query.setExistDutyTime(com.zmn.consts.GlobalConsts.YES);
        query.setWorkType(Arrays.asList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK));
        query.setWorkStatusList(Lists.newArrayList(OrderStatusConsts.WORK_STATUS_TAKE,
                OrderStatusConsts.WORK_STATUS_VISIT, OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE));
        query.setDutyTime(String.format("%s,%s", "", DateUtil.dateFormatToString(orderUserWaitDIO.getDutyTime(), DateUtil.FORMAT_DEFAULT)));
        query.setNonOrderId(orderUserWaitDIO.getOrderId());
        query.setPageSize(1000);
        Integer count = orderWorkListBService.countOrderWorkByQuery(query);
        return ResponseDTO.success(count);
    }

    @Override
    public ResponseDTO<OrderWorkDRO> getOrderWorkByWorkId(@NotNull(message = "入参不能为空") Long workId) {
        log.debug("NormalOrderWorkListRemoteServiceImpl.getOrderWorkByWorkId workId={}", workId);

        OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(workId, workId);
        if (Objects.isNull(orderWork)) {
            return ResponseDTO.fail("订单不存在");
        }
        OrderWorkDRO orderWorkDRO = BeanMapper.map(orderWork, OrderWorkDRO.class);
        // 评价时间
        log.debug("{}cmtCommentListRemoteService.checkOrderComment params={}", workId, orderWork.getOrderId());
        ResponseDTO<CommentDRO> commentDROResponseDTO = cmtCommentListRemoteService.checkOrderComment(orderWork.getOrderId());
        log.debug("{}cmtCommentListRemoteService.checkOrderComment result={}", workId, commentDROResponseDTO);
        if (commentDROResponseDTO.isSuccess() && Objects.nonNull(commentDROResponseDTO.getData())) {
            orderWorkDRO.setCommentTime(DateUtil.parse(commentDROResponseDTO.getData().getCommentTime()));
        }

        // 申请取消
        CancelApplyResultBO cancelApplyResultBO = cancelApplyBService.getWaitCancelInfo(workId, workId);
        if (Objects.equals(cancelApplyResultBO.getUserWaitCancelStatus(), GlobalConsts.YES)) {
            orderWorkDRO.setWaitCancel(GlobalConsts.YES);
            return ResponseDTO.success(orderWorkDRO);
        }
        // 跟单-用户取消
        orderWorkDRO.setWaitCancel(workTrackBService.getUserWaitCancelStatusSrcMaster(workId, workId));

        return ResponseDTO.success(orderWorkDRO);
    }

    @Override
    public ResponseDTO<List<OrderWorkListDRO>> listOrderWorkByQuery(@NotNull(message = "入参不能为空") OrderWorkQueryDIO orderWorkQueryDIO) {
        log.debug("NormalOrderWorkListRemoteServiceImpl.listOrderWorkByQuery {}", orderWorkQueryDIO);
        OrderWorkQuery query = BeanMapper.map(orderWorkQueryDIO, OrderWorkQuery.class);
        // 默认下单时间排序
        query.setOrderField(StringUtils.defaultString(query.getOrderField(), "receiveTime"));
        query.setDefaultOrder(query.getDefaultOrder());
        if (CollectionUtil.isNullOrEmpty(orderWorkQueryDIO.getWorkTypeList())) {
            query.setWorkType(Arrays.asList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK, OrderConsts.ORDER_TYPE_REFUND));
        } else {
            query.setWorkType(orderWorkQueryDIO.getWorkTypeList());
        }
        query.setConcatPhone(orderWorkQueryDIO.getPhone());
        if (Objects.nonNull(orderWorkQueryDIO.getChannelId())) {
            query.setChannelIdList(Lists.newArrayList(orderWorkQueryDIO.getChannelId()));
        }
        if (Objects.nonNull(orderWorkQueryDIO.getResultStatus())) {
            query.setWorkResultStatus(orderWorkQueryDIO.getResultStatus());
        }
        if (NumberUtil.isNullOrZero(query.getPageSize())) {
            query.setPageSize(100);
        }

        List<EsOrderWork> esOrderWorks = orderWorkListBService.listPageOrderWorkByQuery(query);
        if (CollectionUtil.isNullOrEmpty(esOrderWorks)) {
            return ResponseDTO.success(Lists.newArrayList());
        }

        List<OrderWorkListDRO> droList = Lists.newArrayListWithCapacity(esOrderWorks.size());
        esOrderWorks.forEach(esOrderWork -> {
            OrderWorkListDRO dro = new OrderWorkListDRO();
            dro.setPlat(esOrderWork.getPlat());
            dro.setPlatWork(esOrderWork.getPlatWork());
            dro.setOrderId(esOrderWork.getOrderId());
            dro.setWorkId(esOrderWork.getId());
            dro.setStatus(esOrderWork.getStatus());
            dro.setResultStatus(esOrderWork.getResultStatus());
            dro.setChannelId(esOrderWork.getChannelId());
            dro.setOuterId(esOrderWork.getOuterId());
            dro.setReceiveTime(esOrderWork.getReceiveTime());
            dro.setWarrantyProductMaxExpiredTime(esOrderWork.getWarrantyProductMaxExpiredTime());
            dro.setTakeTime(esOrderWork.getTakeTime());

            // 用户信息
            OrderWorkUserInfoDRO orderWorkUserInfoDRO = new OrderWorkUserInfoDRO();
            orderWorkUserInfoDRO.setUserId(esOrderWork.getUserId());

            // 城市
            orderWorkUserInfoDRO.setProvinceId(esOrderWork.getProvinceId());
            orderWorkUserInfoDRO.setProvinceName(esOrderWork.getProvinceName());
            orderWorkUserInfoDRO.setCityId(esOrderWork.getCityId());
            orderWorkUserInfoDRO.setCityName(esOrderWork.getCityName());
            orderWorkUserInfoDRO.setCountyId(esOrderWork.getCountyId());
            orderWorkUserInfoDRO.setCountyName(esOrderWork.getCountyName());

            EsOrderWorkContact contact = esOrderWork.getContact();
            if (Objects.nonNull(contact)) {
                orderWorkUserInfoDRO.setContactName(contact.getContactName());
                orderWorkUserInfoDRO.setGender(contact.getGender());
            }
            dro.setUserInfo(orderWorkUserInfoDRO);

            droList.add(dro);
        });

        return ResponseDTO.success(droList);
    }

    /**
     * 根据手机号查询临时用户订单列表
     * @param orderWorkQueryDIO
     * @return
     */
    @Override
    public ResponseDTO<LayuiTableDO> listTempUserOrderWorkByQuery(OrderWorkQueryDIO orderWorkQueryDIO) {
        log.debug("查询临时用户订单列表入参：[{}]", JSON.toJSONString(orderWorkQueryDIO));
        try {
            LayuiTableDO layuiTableDO = new LayuiTableDO();
            if (StringUtil.isBlank(orderWorkQueryDIO.getPhone())) {
                return ResponseDTO.fail("手机号不能为空");
            }
            OrderWorkQuery query = new OrderWorkQuery();
            query.setConcatPhone(orderWorkQueryDIO.getPhone());
            query.setWorkType(Lists.newArrayList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK));
            query.setPageSize(500);
            query.setOrderField("receiveTime");
            // 不查询未成单数据
            query.setNonTagId(OrderTagConsts.TAG_ID_UN_AVAILABLE_SERVICE);
            List<EsOrderWork> esOrderWorkList = orderWorkListBService.listTempUserOrderWorkByQuery(query);
            if (CollectionUtil.isNullOrEmpty(esOrderWorkList)) {
                layuiTableDO.setCount(0);
                layuiTableDO.setData(Lists.newArrayList());
                return ResponseDTO.success(layuiTableDO);
            }
            List<TempUserOrderDRO> list = Lists.newArrayListWithCapacity(esOrderWorkList.size());
            esOrderWorkList.forEach(esOrderWork -> {
                TempUserOrderDRO dro = new TempUserOrderDRO();
                dro.setOrderId(esOrderWork.getOrderId());
                dro.setWorkId(esOrderWork.getId());
                dro.setShowProductName(esOrderWork.getProductList().get(0).getShowProductName());
                dro.setDutyTime(esOrderWork.getDutyTime());
                dro.setContactName(esOrderWork.getContact().getContactName());
                dro.setProvinceName(esOrderWork.getProvinceName());
                dro.setCityName(esOrderWork.getCityName());
                dro.setCountyName(esOrderWork.getCountyName());
                dro.setStreet(esOrderWork.getContact().getStreet());
                dro.setAddress(esOrderWork.getContact().getAddress());
                dro.setStatus(OrderStatusConsts.getOrderStatus(esOrderWork.getStatus(), esOrderWork.getResultStatus()));
                dro.setIsComment(Objects.equals(GlobalConsts.YES, esOrderWork.getCommentStatus()));
                dro.setWaitCancel(esOrderWork.getWaitCancel());
                dro.setPrepayStatus(esOrderWork.getPrepayStatus());
                dro.setUserId(esOrderWork.getUserId());
                list.add(dro);
            });
            layuiTableDO.setCount(list.size());
            layuiTableDO.setData(list);
            return ResponseDTO.success(layuiTableDO);
        } catch (Exception e) {
            log.error("查询临时用户列表接口异常：[{}]", e.getMessage());
            e.printStackTrace();
            return ResponseDTO.fail("查询临时用户列表接口异常");
        }
    }

    @Override
    public ResponseDTO<LayuiTableDO<OrderRefundDetailDRO>> listOrderRefundDetailByQuery(@NotNull(message = "入参不能为空") OrderRefundDetailDIO orderRefundDetailDIO) {
        log.debug("NormalOrderWorkListRemoteServiceImpl.listOrderRefundDetailByQuery params={}", orderRefundDetailDIO);

        // 查询退款单
        OrderWorkQuery query = new OrderWorkQuery();
        query.setOrderId(orderRefundDetailDIO.getOrderId());
        query.setWorkType(Arrays.asList(OrderConsts.ORDER_TYPE_REFUND));
        query.setOrderField("receiveTime");
        query.setPageIndex(orderRefundDetailDIO.getPageIndex());
        query.setPageSize(orderRefundDetailDIO.getPageSize());
        List<EsOrderWork> esOrderWorkList = orderWorkListBService.listPageOrderWorkByQuery(query);
        if (CollectionUtil.isNullOrEmpty(esOrderWorkList)) {
            LayuiTableDO<OrderRefundDetailDRO> layuiTableDO = new LayuiTableDO();
            layuiTableDO.setCount(GlobalConsts.NONE);
            return ResponseDTO.success(layuiTableDO);
        }

        // 查询退款交易
        List<Long> workIds = esOrderWorkList.stream()
                .map(EsOrderWork::getId)
                .collect(Collectors.toList());
        List<OrderPay> orderPays = orderPayService.listOrderPayByOrderIdAndWorkIdsAndTradeTypeSrc(orderRefundDetailDIO.getOrderId(), workIds, PayConsts.PAY_TRADE_TYPE_REFUND);
        if (CollectionUtil.isNullOrEmpty(orderPays)) {
            LayuiTableDO<OrderRefundDetailDRO> layuiTableDO = new LayuiTableDO();
            layuiTableDO.setCount(GlobalConsts.NONE);
            return ResponseDTO.success(layuiTableDO);
        }

        Map<Long, List<OrderPay>> orderPayMap = new HashMap<>();
        for (OrderPay orderPay : orderPays) {
            List<OrderPay> orderPayList = orderPayMap.get(orderPay.getWorkId());
            if (CollectionUtil.isNullOrEmpty(orderPayList)) {
                orderPayList = new ArrayList<>();
            }
            orderPayList.add(orderPay);
            orderPayMap.put(orderPay.getWorkId(), orderPayList);
        }

        // 组装退款明细
        List<OrderRefundDetailDRO> orderRefundDetailDROS = new ArrayList<>(esOrderWorkList.size());
        for (EsOrderWork esOrderWork : esOrderWorkList) {
            List<OrderPay> refundOrderWorkList = orderPayMap.get(esOrderWork.getId());
            if (CollectionUtil.isNullOrEmpty(refundOrderWorkList)) {
                continue;
            }

            OrderRefundDetailDRO dro = new OrderRefundDetailDRO();
            dro.setRefundAmount(esOrderWork.getRefundAmount());
            dro.setRefundTime(esOrderWork.getLastRefundAmountTime());

            OrderPay orderPay = refundOrderWorkList.get(0);
            if (Objects.equals(orderPay.getRefundType(), RefundTypeEnum.ORIGINAL_REFUND.getType())) {
                dro.setRefundType(RefundTypeEnum.ORIGINAL_REFUND.getDesc());
            } else if (Objects.equals(orderPay.getPayTargetChannelId(), RefundTypeEnum.CASH_REFUND.getType())){
                dro.setRefundType(RefundTypeEnum.CASH_REFUND.getDesc());
            }else if (Objects.equals(orderPay.getPayTargetChannelId(), RefundTypeEnum.WEIXIN_REFUND.getType())
                    || Objects.equals(orderPay.getPayTargetChannelId(), RefundTypeEnum.ALIPAY_REFUND.getType())
                    || Objects.equals(orderPay.getPayTargetChannelId(), RefundTypeEnum.BANK_REFUND.getType())
            ){
                dro.setRefundType(String.format("%s（%s）", RefundTypeEnum.getRefundTypeName(orderPay.getPayTargetChannelId()), orderPay.getPayeeThirdAccount()));
            }

            orderRefundDetailDROS.add(dro);
        }

        LayuiTableDO<OrderRefundDetailDRO> layuiTableDO = new LayuiTableDO();
        layuiTableDO.setCount(orderRefundDetailDROS.size());
        layuiTableDO.setData(orderRefundDetailDROS);
        log.debug("NormalOrderWorkListRemoteServiceImpl.listOrderRefundDetailByQuery result={}", layuiTableDO);
        return ResponseDTO.success(layuiTableDO);
    }

    @Override
    public ResponseDTO<Long> getDuplicateOrderIdByOrderIdAndWorkId(Long orderId, Long workId) {
        log.debug("#NormalOrderWorkListRemoteServiceImpl#getDuplicateOrderIdByOrderIdAndWorkId 入参 workId={}", workId);
        try {
            OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
            // 处理重复工单ID
            Long duplicateOrderId = duplicateOrderBService.findDuplicateOrderId(orderWork);
            return ResponseDTO.success(duplicateOrderId);
        } catch (Exception e) {
            log.error("#NormalOrderWorkListRemoteServiceImpl#getDuplicateOrderIdByOrderIdAndWorkId异常 workId={}", e);
            return ResponseDTO.fail("查询取消重复单接口异常");
        }
    }
}
